package com.jingxuan.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Locale;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.jingxuan.common.exception.BusinessException;
import com.jingxuan.common.result.ResultCode;
import com.jingxuan.dto.request.CompareProductsRequest;
import com.jingxuan.dto.request.CompareProductsRequest.UserBehavior;
import com.jingxuan.dto.request.ProductListRequest;
import com.jingxuan.dto.request.ProductsKeywordSearchRequest;
import com.jingxuan.dto.request.ProductsWeightSearchRequest;
import com.jingxuan.dto.response.ProductStandardizeResponse;
import com.jingxuan.dto.response.ProductResponse;
import com.jingxuan.dto.response.ProductsResponse;
import com.jingxuan.dto.response.CompareProductsResponse;
import com.jingxuan.dto.response.ProductComparisonItemResponse;
import com.jingxuan.dto.response.SimilarProductsResponse;
import com.jingxuan.entity.Product;
import com.jingxuan.entity.User;
import com.jingxuan.entity.Comment;
import com.jingxuan.mapper.ProductsMapper;
import com.jingxuan.mapper.RecommendMapper;
import com.jingxuan.mapper.RecommendMapper.ProductFeatureDto;
import com.jingxuan.mapper.UserMapper;
import com.jingxuan.mapper.CommentsMapper;
import com.jingxuan.service.ProductsService;
import com.jingxuan.util.JsonUtil;
import com.jingxuan.util.RankAlgorithm;
import com.jingxuan.util.ProductsRecommendAlgorithm;
import com.jingxuan.util.RankAlgorithm.ProductFeature;
import com.jingxuan.util.RankAlgorithm.RecommendationResult;
import com.jingxuan.util.RankAlgorithm.ScoredProduct;
import com.jingxuan.util.SearchKeywordProcessor;
import com.jingxuan.util.SearchKeywordProcessor.KeywordInfo;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 商品服务实现类
 * 提供商品搜索、相似商品推荐、商品数据标准化等功能
 * 
 * @author jingxuan
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ProductsServiceImpl implements ProductsService {

    // 默认页码
    private static final int DEFAULT_PAGE = 1;
    // 默认每页显示数量
    private static final int DEFAULT_PAGE_SIZE = 20;
    // 每页最大显示数量
    private static final int MAX_PAGE_SIZE = 100;
    // 相似商品默认返回数量
    private static final int DEFAULT_SIMILAR_LIMIT = 5;
    // 相似商品最大返回数量
    private static final int MAX_SIMILAR_LIMIT = 50;

    @Autowired
    private ProductsMapper productsMapper;

    @Autowired
    private RecommendMapper recommendMapper;

    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private CommentsMapper commentsMapper;
    
    @Override
    public ProductsResponse searchProducts(ProductsKeywordSearchRequest request) {
        if (request == null) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "请求参数不能为空");
        }

        // 获取并处理搜索关键词
        String keyword = request.getKeyword() != null ? request.getKeyword().trim() : "";
        if (keyword.isEmpty()) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "搜索关键词不能为空");
        }

        
        int page = resolvePositiveNumber(request.getPage(), DEFAULT_PAGE);
        int pageSize = Math.min(resolvePositiveNumber(request.getPageSize(), DEFAULT_PAGE_SIZE), MAX_PAGE_SIZE);
        int offset = Math.max(0, (page - 1) * pageSize);

        // 首先检查关键词是否精确匹配某个type字段
        List<String> allTypes = productsMapper.selectAllProductTypes();
        boolean isTypeMatch = false;
        String matchedType = null;
        
        if (allTypes != null) {
            for (String type : allTypes) {
                if (type != null && keyword.equals(type.trim())) {
                    isTypeMatch = true;
                    matchedType = type;
                    break;
                }
            }
        }

        List<Product> products;
        Integer totalCount;
        boolean isBrandTypeMatch = false; // 提前声明变量，扩大作用域

        if (isTypeMatch) {
            // 如果关键词精确匹配type字段，则只返回该type的商品
            log.info("搜索关键词精确匹配type字段，使用type搜索：{}", matchedType);
            products = productsMapper.searchProductsByType(
                    matchedType,
                    request.getPlatformId(),
                    offset,
                    pageSize);
            totalCount = productsMapper.countProductsByType(
                    matchedType,
                    request.getPlatformId());
        } else {
            // 如果没有匹配的type，则使用智能搜索算法
            log.info("搜索关键词不匹配任何type字段，使用智能搜索算法：{}", keyword);
            KeywordInfo keywordInfo = SearchKeywordProcessor.processKeyword(keyword);
            
            // 检查是否为品牌+产品类型组合
            isBrandTypeMatch = keywordInfo.getBrand() != null && keywordInfo.getType() != null;
            
            if (isBrandTypeMatch) {
                // 品牌+产品类型组合使用特殊搜索方法
                log.info("检测到品牌+产品类型组合，使用品牌类型搜索：{}，品牌：{}，类型：{}", keyword, keywordInfo.getBrand(), keywordInfo.getType());
                products = productsMapper.searchBrandTypeProducts(
                        keyword,
                        keywordInfo.getBrand(),
                        keywordInfo.getType(),
                        request.getPlatformId(),
                        offset,
                        pageSize);
                totalCount = productsMapper.countBrandTypeProducts(
                        keyword,
                        keywordInfo.getBrand(),
                        keywordInfo.getType(),
                        request.getPlatformId());
            } else {
                // 普通搜索
                products = productsMapper.searchProducts(
                        keywordInfo.getFuzzyKeyword(),
                        keywordInfo.getExactKeyword(),
                        keywordInfo.getPrefixKeyword(),
                        keywordInfo.getTypeExactKeyword(),
                        keywordInfo.getTypePrefixKeyword(),
                        keywordInfo.getPreciseFuzzyKeyword(),
                        request.getPlatformId(),
                        offset,
                        pageSize);
                totalCount = productsMapper.countProducts(
                        keywordInfo.getFuzzyKeyword(),
                        keywordInfo.getExactKeyword(),
                        keywordInfo.getPrefixKeyword(),
                        keywordInfo.getTypeExactKeyword(),
                        keywordInfo.getTypePrefixKeyword(),
                        keywordInfo.getPreciseFuzzyKeyword(),
                        request.getPlatformId());
            }
        }

        // 构建响应对象
        ProductsResponse response = new ProductsResponse();
        response.setProducts(products.stream().map(this::toProductResponse).collect(Collectors.toList()));
        response.setTotalCount(totalCount == null ? 0 : totalCount);
        response.setPage(page);
        response.setPageSize(pageSize);

        // 记录日志
        log.info("寻找商品完成，关键词={}，平台={}，页码={}，每页数量={}，商品总数={}，搜索模式={}",
                keyword, request.getPlatformId(), page, pageSize, response.getTotalCount(),
                isTypeMatch ? "TYPE精确匹配" : (isBrandTypeMatch ? "品牌类型匹配" : "智能搜索"));
        return response;
    }

    @Override
    public ProductsResponse searchProductsWithWeights(ProductsWeightSearchRequest request) {
        if (request == null) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "请求参数不能为空");
        }

        // 获取并处理搜索关键词
        String keyword = request.getKeyword() != null ? request.getKeyword().trim() : "";
        if (keyword.isEmpty()) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "搜索关键词不能为空");
        }

        int page = resolvePositiveNumber(request.getPage(), DEFAULT_PAGE);
        int pageSize = Math.min(resolvePositiveNumber(request.getPageSize(), DEFAULT_PAGE_SIZE), MAX_PAGE_SIZE);
        int offset = Math.max(0, (page - 1) * pageSize);

        // 首先检查关键词是否精确匹配某个type字段
        List<String> allTypes = productsMapper.selectAllProductTypes();
        boolean isTypeMatch = false;
        String matchedType = null;
        
        if (allTypes != null) {
            for (String type : allTypes) {
                if (type != null && keyword.equals(type.trim())) {
                    isTypeMatch = true;
                    matchedType = type;
                    break;
                }
            }
        }

        List<Product> products;
        Integer totalCount;
        boolean isBrandTypeMatch = false; // 提前声明变量，扩大作用域

        if (isTypeMatch) {
            // 如果关键词精确匹配type字段，则只返回该type的商品
            log.info("带权重搜索关键词精确匹配type字段，使用type搜索：{}", matchedType);
            products = productsMapper.searchProductsByType(
                    matchedType,
                    request.getPlatformId(),
                    offset,
                    pageSize * 2); // 获取更多候选商品用于重排序
            totalCount = productsMapper.countProductsByType(
                    matchedType,
                    request.getPlatformId());
        } else {
            // 如果没有匹配的type，则使用原有的智能搜索算法
            log.info("带权重搜索关键词不匹配任何type字段，使用智能搜索算法：{}", keyword);
            KeywordInfo keywordInfo = SearchKeywordProcessor.processKeyword(keyword);
            
            // 检查是否为品牌+产品类型组合
            isBrandTypeMatch = keywordInfo.getBrand() != null && keywordInfo.getType() != null;
            
            if (isBrandTypeMatch) {
                // 品牌+产品类型组合使用特殊搜索方法
                log.info("带权重搜索检测到品牌+产品类型组合，使用品牌类型搜索：{}，品牌：{}，类型：{}", keyword, keywordInfo.getBrand(), keywordInfo.getType());
                products = productsMapper.searchBrandTypeProducts(
                        keyword,
                        keywordInfo.getBrand(),
                        keywordInfo.getType(),
                        request.getPlatformId(),
                        offset,
                        pageSize * 2); // 获取更多候选商品用于重排序
                totalCount = productsMapper.countBrandTypeProducts(
                        keyword,
                        keywordInfo.getBrand(),
                        keywordInfo.getType(),
                        request.getPlatformId());
            } else {
                // 普通搜索
                products = productsMapper.searchProducts(
                        keywordInfo.getFuzzyKeyword(),
                        keywordInfo.getExactKeyword(),
                        keywordInfo.getPrefixKeyword(),
                        keywordInfo.getTypeExactKeyword(),
                        keywordInfo.getTypePrefixKeyword(),
                        keywordInfo.getPreciseFuzzyKeyword(),
                        request.getPlatformId(),
                        offset,
                        pageSize * 2); // 获取更多候选商品用于重排序
                totalCount = productsMapper.countProducts(
                        keywordInfo.getFuzzyKeyword(),
                        keywordInfo.getExactKeyword(),
                        keywordInfo.getPrefixKeyword(),
                        keywordInfo.getTypeExactKeyword(),
                        keywordInfo.getTypePrefixKeyword(),
                        keywordInfo.getPreciseFuzzyKeyword(),
                        request.getPlatformId());
            }
        }

        // 如果没有商品，直接返回
        if (products == null || products.isEmpty()) {
            ProductsResponse response = new ProductsResponse();
            response.setProducts(Collections.emptyList());
            response.setTotalCount(totalCount == null ? 0 : totalCount);
            response.setPage(page);
            response.setPageSize(pageSize);
            return response;
        }

        // 获取商品特征数据用于重排序
        List<String> productIds = products.stream()
                .map(Product::getId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());

        List<ProductFeatureDto> featureDtos = recommendMapper.getProductFeaturesByIds(productIds);
        Map<String, ProductFeatureDto> featureMap = featureDtos != null ?
                featureDtos.stream().collect(Collectors.toMap(ProductFeatureDto::getProductId, Function.identity())) :
                Collections.emptyMap();

        // 使用用户权重重新排序商品
        List<Product> reorderedProducts = reorderProductsWithWeights(products, featureMap, request);
        
        log.info("权重重排序完成，原始商品数量={}，重排序后数量={}，权重配置={}/{}/{}/{}",
                products.size(), reorderedProducts.size(),
                request.getPriceWeight(), request.getReputationWeight(),
                request.getHeatWeight(), request.getTimelinessWeight());

        // 限制返回数量
        List<Product> finalProducts = reorderedProducts.stream()
                .limit(pageSize)
                .collect(Collectors.toList());

        // 构建响应对象
        ProductsResponse response = new ProductsResponse();
        response.setProducts(finalProducts.stream().map(this::toProductResponse).collect(Collectors.toList()));
        response.setTotalCount(totalCount == null ? 0 : totalCount);
        response.setPage(page);
        response.setPageSize(pageSize);

        log.info("带权重搜索商品完成，关键词={}，权重配置={}/{}/{}/{}, 页码={}，每页数量={}，商品总数={}，搜索模式={}",
                keyword, request.getPriceWeight(), request.getReputationWeight(),
                request.getHeatWeight(), request.getTimelinessWeight(), page, pageSize, response.getTotalCount(),
                isTypeMatch ? "TYPE精确匹配" : (isBrandTypeMatch ? "品牌类型匹配" : "智能搜索"));
        return response;
    }

    /**
     * 根据用户权重重新排序商品
     */
    private List<Product> reorderProductsWithWeights(List<Product> products,
                                                   Map<String, ProductFeatureDto> featureMap,
                                                   ProductsWeightSearchRequest request) {
        if (products == null || products.isEmpty()) {
            return Collections.emptyList();
        }

        // 计算价格范围用于归一化
        double minPrice = Double.POSITIVE_INFINITY;
        double maxPrice = Double.NEGATIVE_INFINITY;
        
        for (Product product : products) {
            if (product.getPrice() != null) {
                double price = product.getPrice().doubleValue();
                if (price > 0) {
                    minPrice = Math.min(minPrice, price);
                    maxPrice = Math.max(maxPrice, price);
                }
            }
        }
        
        // 边界处理
        if (Double.isInfinite(minPrice) || Double.isInfinite(maxPrice)) {
            minPrice = 0;
            maxPrice = 0;
        }

        // 计算每个商品的综合得分
        List<WeightedProduct> weightedProducts = new ArrayList<>();
        
        for (Product product : products) {
            ProductFeatureDto feature = featureMap.get(product.getId());
            
            // 计算各维度得分
            double priceScore = calculatePriceScore(product, minPrice, maxPrice);
            double reputationScore = calculateReputationScore(feature);
            double heatScore = calculateHeatScore(feature);
            double timelinessScore = calculateTimelinessScore(feature);
            
            // 直接使用前端传来的权重，前端已经计算好了最终权重值
            double finalScore = request.getPriceWeight() * priceScore +
                              request.getReputationWeight() * reputationScore +
                              request.getHeatWeight() * heatScore +
                              request.getTimelinessWeight() * timelinessScore;
            
            // 记录调试信息
            log.debug("商品 {} 权重计算: 价格={}×{}, 口碑={}×{}, 热度={}×{}, 时效={}×{}, 最终得分={}",
                    product.getId(),
                    priceScore, request.getPriceWeight(),
                    reputationScore, request.getReputationWeight(),
                    heatScore, request.getHeatWeight(),
                    timelinessScore, request.getTimelinessWeight(),
                    finalScore);
            
            weightedProducts.add(new WeightedProduct(product, finalScore));
        }

        // 按得分排序
        return weightedProducts.stream()
                .sorted(Comparator.comparingDouble(WeightedProduct::getScore).reversed())
                .map(WeightedProduct::getProduct)
                .collect(Collectors.toList());
    }

    /**
     * 计算价格得分
     */
    private double calculatePriceScore(Product product, double minPrice, double maxPrice) {
        if (product.getPrice() == null || maxPrice <= minPrice) {
            return 50.0; // 默认中等分
        }
        
        double price = product.getPrice().doubleValue();
        // 价格得分 = 30 + 70 × (最高价 - 当前价) ÷ (最高价 - 最低价)
        double score = 30.0 + 70.0 * (maxPrice - price) / (maxPrice - minPrice);
        return Math.max(0, Math.min(100, score));
    }

    /**
     * 计算口碑得分
     */
    private double calculateReputationScore(ProductFeatureDto feature) {
        if (feature == null || feature.getPositiveRate() == null) {
            return 50.0; // 默认中等分
        }
        
        // 简化版口碑得分，主要基于好评率
        double goodRate = feature.getPositiveRate() * 100;
        return Math.max(0, Math.min(100, goodRate));
    }

    /**
     * 计算热度得分
     */
    private double calculateHeatScore(ProductFeatureDto feature) {
        if (feature == null) {
            return 30.0; // 默认较低分
        }
        
        // 基于评论数和平均点赞数计算热度（因为DTO中没有加购数）
        int commentCount = feature.getCommentCount() != null ? feature.getCommentCount() : 0;
        double averageLikes = feature.getAverageLikes() != null ? feature.getAverageLikes() : 0.0;
        
        // 热度得分 = min(100, 评论数量 × 5 + 平均点赞数 × 2)
        double score = Math.min(100, commentCount * 5.0 + averageLikes * 2.0);
        return Math.max(0, score);
    }

    /**
     * 计算时效得分
     */
    private double calculateTimelinessScore(ProductFeatureDto feature) {
        if (feature == null || feature.getLastCommentTime() == null) {
            return 30.0; // 默认较低分
        }
        
        // 基于最后评论时间计算时效
        long days = java.time.temporal.ChronoUnit.DAYS.between(feature.getLastCommentTime(), java.time.LocalDateTime.now());
        // 时效得分 = max(0, 100 - 天数差 × 5)
        double score = Math.max(0, 100 - days * 5.0);
        return Math.min(100, score);
    }

    /**
     * 带权重的商品包装类
     */
    private static class WeightedProduct {
        private final Product product;
        private final double score;

        public WeightedProduct(Product product, double score) {
            this.product = product;
            this.score = score;
        }

        public Product getProduct() {
            return product;
        }

        public double getScore() {
            return score;
        }
    }

    @Override
    public com.jingxuan.dto.response.ProductResponse getProductDetail(String productId) {
        if (productId == null) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "商品ID不能为空");
        }

        Product product = productsMapper.selectById(productId);
        if (product == null) {
            throw new BusinessException(ResultCode.PRODUCT_NOT_FOUND, "商品未找到");
        }

        log.info("获取商品详情完成，商品ID={}", productId);
        return toProductResponse(product);
    }

    /**
     * 基础比价：根据给定的商品ID集合计算排序结果
     */
    @Override
    public CompareProductsResponse compareProducts(CompareProductsRequest request) {
        if (request == null) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "请求参数不能为空");
        }

        List<String> productIds = request.getProductIds();
        if (CollectionUtils.isEmpty(productIds)) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "产品ID列表不能为空");
        }

        // 去重并转换为列表
        List<String> normalizedIds = productIds.stream()
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        if (normalizedIds.isEmpty()) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "产品ID列表不合法");
        }

        List<Product> products = productsMapper.selectByIds(normalizedIds);
        if (products == null || products.isEmpty()) {
            throw new BusinessException(ResultCode.PRODUCT_NOT_FOUND, "未找到对应的商品信息");
        }

        Map<String, Product> productMap = products.stream()
                .filter(p -> p.getId() != null)
                .collect(Collectors.toMap(
                        Product::getId,
                        Function.identity(),
                        (left, right) -> left,
                        LinkedHashMap::new
                ));

        if (productMap.isEmpty()) {
            throw new BusinessException(ResultCode.PRODUCT_NOT_FOUND, "未找到对应的商品信息");
        }

        // 推断用户偏好标签
        List<String> preferenceTags = resolvePreferenceTags(request);
        List<String> algorithmTags = CollectionUtils.isEmpty(preferenceTags) ? null : preferenceTags;
        if (!CollectionUtils.isEmpty(algorithmTags)) {
            log.info("比价使用的偏好标签：{}", algorithmTags);
        }

        // 查询所有商品的特征数据
        List<ProductFeatureDto> featureDtos = recommendMapper.getProductFeaturesByIds(new ArrayList<>(productMap.keySet()));
        // 构建比价结果列表
        List<ProductComparisonItemResponse> comparisonItems = new ArrayList<>();
        Set<String> appended = new LinkedHashSet<>();

        if (featureDtos != null && !featureDtos.isEmpty()) {
            // 转换为算法用的Feature对象
            List<ProductFeature> features = featureDtos.stream()
                    .map(this::convertToProductFeature)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());

            if (!features.isEmpty()) {
                RecommendationResult recommendationResult = ProductsRecommendAlgorithm.recommend(
                        features,
                        algorithmTags
                );

                int rank = 1;
                for (ScoredProduct scored : recommendationResult.getProducts()) {
                    Product product = productMap.get(scored.getFeature().getProductId());
                    if (product == null) {
                        continue;
                    }
                    comparisonItems.add(toComparisonItem(product, scored, rank++));
                    appended.add(product.getId());
                }
            }
        }

        // 如果比价结果为空，则使用价格降级策略
        if (comparisonItems.isEmpty()) {
            comparisonItems.addAll(buildPriceFallbackComparison(productMap.values(), Collections.emptySet(), 1));
        } else if (appended.size() < productMap.size()) {   
            // 比价结果不足，使用价格降级策略
            comparisonItems.addAll(buildPriceFallbackComparison(productMap.values(), appended, comparisonItems.size() + 1));
        }

        // 构建响应对象
        CompareProductsResponse response = new CompareProductsResponse();
        response.setProducts(comparisonItems);
        log.info("比价完成, 商品ID数量={}, 比价结果数量={}, 偏好标签={}", normalizedIds.size(), comparisonItems.size(), algorithmTags);
        return response;
    }

    /**
     * 价格降级策略：根据商品价格进行排序
     */
    private List<ProductComparisonItemResponse> buildPriceFallbackComparison(Collection<Product> candidates,
                                                                              Set<String> excludeIds,
                                                                              int startRank) {
        // 如果候选商品为空，则返回空列表
        if (candidates == null || candidates.isEmpty()) {
            return Collections.emptyList();
        }
        // 过滤掉已排除的商品
        Set<String> excluded = excludeIds == null ? Collections.emptySet() : excludeIds;
        List<Product> filtered = candidates.stream()
                .filter(Objects::nonNull)
                .filter(product -> product.getId() != null && !excluded.contains(product.getId()))
                .collect(Collectors.toList());
        if (filtered.isEmpty()) {
            return Collections.emptyList();
        }
        // 计算价格范围
        double minPrice = filtered.stream()
                .map(Product::getPrice)
                .filter(Objects::nonNull)
                .mapToDouble(BigDecimal::doubleValue)
                .min()
                .orElse(0.0);
        double maxPrice = filtered.stream()
                .map(Product::getPrice)
                .filter(Objects::nonNull)
                .mapToDouble(BigDecimal::doubleValue)
                .max()
                .orElse(minPrice);
        double range = Math.max(1.0, maxPrice - minPrice);

        // 构建比价结果列表
        List<ProductComparisonItemResponse> items = new ArrayList<>();
        // 设置起始排名
        final int[] rank = {startRank};
        // 按价格排序
        filtered.stream()
                .sorted(Comparator.comparingDouble(product -> toPriceValue(product.getPrice())))
                .forEach(product -> {
                    double priceValue = toPriceValue(product.getPrice());
                    double normalized = maxPrice == minPrice
                            ? 100.0
                            : 100.0 - ((priceValue - minPrice) / range) * 100.0;
                    double score = Math.max(0.0, Math.min(100.0, normalized));
                    items.add(toComparisonItem(product, null, rank[0], score));
                    rank[0]++;
                });
        return items;
    }

    /**
     * 解析偏好标签
     */
    private List<String> resolvePreferenceTags(CompareProductsRequest request) {
        if (request == null) {
            return Collections.emptyList();
        }

        List<String> directTags = sanitizeTags(request.getPreferenceTags());
        if (!directTags.isEmpty()) {
            return directTags;
        }

        List<String> inferredTags = inferPreferenceTagsFromBehaviors(request.getUserBehaviors());
        if (!inferredTags.isEmpty()) {
            return inferredTags;
        }

        if (request.getUserId() != null) {
            return loadStoredPreferenceTags(request.getUserId());
        }
        return Collections.emptyList();
    }

    /**
     * 清理标签列表
     */
    private List<String> sanitizeTags(List<String> tags) {
        if (CollectionUtils.isEmpty(tags)) {
            return Collections.emptyList();
        }
        Map<String, String> unique = new LinkedHashMap<>();
        for (String tag : tags) {
            if (!StringUtils.hasText(tag)) {
                continue;
            }
            String trimmed = tag.trim();
            if (trimmed.isEmpty()) {
                continue;
            }
            String key = trimmed.toLowerCase(Locale.ROOT);
            unique.putIfAbsent(key, trimmed);
        }
        return unique.values().stream()
                .limit(10)
                .collect(Collectors.toList());
    }

    /**
     * 从用户行为中推断偏好标签
     */
    private List<String> inferPreferenceTagsFromBehaviors(List<UserBehavior> behaviors) {
        if (CollectionUtils.isEmpty(behaviors)) {
            return Collections.emptyList();
        }
        // 计算用户行为得分
        Map<String, BehaviorAggregate> aggregates = new LinkedHashMap<>();
        for (UserBehavior behavior : behaviors) {
            if (behavior == null || !StringUtils.hasText(behavior.getProductType())) {
                continue;
            }
            double score = calculateBehaviorScore(behavior);
            if (score <= 0) {
                continue;
            }
            String normalized = behavior.getProductType().trim();
            String key = normalized.toLowerCase(Locale.ROOT);
            aggregates.compute(key, (k, existing) -> {
                if (existing == null) {
                    return new BehaviorAggregate(normalized, score);
                }
                existing.increase(score);
                return existing;
            });
        }
        return aggregates.values().stream()
                .sorted(Comparator.comparingDouble(BehaviorAggregate::score).reversed())
                .map(BehaviorAggregate::tag)
                .limit(5)
                .collect(Collectors.toList());
    }

    /**
     * 计算用户行为得分
     */
    private double calculateBehaviorScore(UserBehavior behavior) {
        double score = 0.0;
        if (behavior.getViewCount() != null) {
            score += Math.max(0, behavior.getViewCount());
        }
        if (behavior.getCartCount() != null) {
            score += Math.max(0, behavior.getCartCount()) * 2.5;
        }
        if (behavior.getPurchaseCount() != null) {
            score += Math.max(0, behavior.getPurchaseCount()) * 5.0;
        }
        if (behavior.getSpendAmount() != null) {
            score += Math.max(0.0, behavior.getSpendAmount()) / 20.0;
        }
        return score;
    }

    /**
     * 加载用户偏好标签
     */
    private List<String> loadStoredPreferenceTags(Long userId) {
        try {
            User user = userMapper.selectById(userId);
            if (user == null || !StringUtils.hasText(user.getPreferences())) {
                return Collections.emptyList();
            }
            List<String> stored = JsonUtil.jsonToList(user.getPreferences());
            List<String> sanitized = sanitizeTags(stored);
            if (!sanitized.isEmpty()) {
                log.info("从用户历史偏好中解析出标签，userId={}, tags={}", userId, sanitized);
            }
            return sanitized;
        } catch (Exception ex) {
            log.warn("读取用户偏好标签失败，userId={}", userId, ex);
            return Collections.emptyList();
        }
    }

    /**
     * 用户行为聚合
     */
    private static final class BehaviorAggregate {
        private final String tag;
        private double score;

        private BehaviorAggregate(String tag, double score) {
            this.tag = tag;
            this.score = score;
        }

        private void increase(double delta) {
            this.score += delta;
        }

        private String tag() {
            return tag;
        }

        private double score() {
            return score;
        }
    }

    /**
     * 构建比价结果项
     */
    private ProductComparisonItemResponse toComparisonItem(Product product,
                                                            ScoredProduct scoredProduct,
                                                            int rank) {
        return toComparisonItem(product, scoredProduct, rank, null);
    }

    /**
     * 构建比价结果项
     */
    private ProductComparisonItemResponse toComparisonItem(Product product,
                                                            ScoredProduct scoredProduct,
                                                            int rank,
                                                            Double fallbackScore) {
        ProductComparisonItemResponse item = new ProductComparisonItemResponse();
        item.setProductId(product.getId());
        item.setProductName(product.getProductName());
        item.setPrice(product.getPrice());
        item.setPlatformName(resolvePlatformName(product.getPlatformId()));
        item.setImageUrl(product.getPictureUrl());
        item.setSalesQuantity(product.getSalesQuantity());
        item.setApplauseRate(product.getApplauseRate());
        item.setRank(rank);

        if (scoredProduct != null) {
            item.setBaseScore(roundScore(scoredProduct.getBaseScore()));
            item.setPreferenceScore(roundScore(scoredProduct.getPreferenceScore()));
            item.setTagBonus(roundScore(scoredProduct.getTagBonus()));
            item.setFinalScore(roundScore(scoredProduct.getFinalScore()));
        } else if (fallbackScore != null) {
            double rounded = roundScore(fallbackScore);
            item.setBaseScore(rounded);
            item.setFinalScore(rounded);
            item.setPreferenceScore(null);
            item.setTagBonus(null);
        }
        return item;
    }

    private double toPriceValue(BigDecimal price) {
        if (price == null) {
            return Double.MAX_VALUE;
        }
        return price.doubleValue();
    }

    private double roundScore(double value) {
        if (!Double.isFinite(value)) {
            return 0.0;
        }
        return Math.round(value * 100.0) / 100.0;
    }

    
    /**
     * 获取相似商品
     * 
     * 通过给定商品ID和数量，先查找该商品，根据类型/平台等条件从数据库中查找候选商品集合，并提取特征数据，通过推荐算法对候选商品进行排序推荐，返回推荐结果（ProductResponse 列表）。
     * 若没有足够特征数据或推荐异常，则退化为简单候选商品返回
     */
    @Override
    public SimilarProductsResponse getSimilarProducts(String productId, Integer limit) {
        if (productId == null) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "商品id不能为空");
        }

        Product current = productsMapper.selectById(productId);
        if (current == null) {
            throw new BusinessException(ResultCode.PRODUCT_NOT_FOUND);
        }

        // 计算最终返回数量和候选抓取数量
        int resolvedLimit = Math.min(resolvePositiveNumber(limit, DEFAULT_SIMILAR_LIMIT), MAX_SIMILAR_LIMIT);
        // 抓取的候选数量略大于返回数量，以便推荐算法有更多备选
        int candidateFetchLimit = Math.min(Math.max(resolvedLimit * 3, resolvedLimit + 2), MAX_SIMILAR_LIMIT * 2);

        // 依次用：同类型同平台、全平台同类型、全平台全类型 尽量多地获取候选商品
        Map<String, Product> candidateMap = new LinkedHashMap<>();
        addCandidates(candidateMap, productsMapper.findSimilarProducts(
                current.getType(),
                current.getPlatformId(),
                productId,
                candidateFetchLimit
        ));

        // 如候选不足，再查全平台同类型
        if (candidateMap.size() < resolvedLimit && current.getPlatformId() != null) {
            addCandidates(candidateMap, productsMapper.findSimilarProducts(
                    null,
                    current.getPlatformId(),
                    productId,
                    candidateFetchLimit
            ));
        }

        // 如仍然不足，再查全部商品
        if (candidateMap.isEmpty()) {
            addCandidates(candidateMap, productsMapper.findSimilarProducts(
                    null,
                    null,
                    productId,
                    candidateFetchLimit
            ));
        }

        // 汇总所有候选商品
        List<Product> candidateProducts = new ArrayList<>(candidateMap.values());
        if (candidateProducts.isEmpty()) {
            log.info("没有找到相似商品，商品id={}，返回空列表", productId);
            return buildSimilarProductsResponse(resolvedLimit, Collections.emptyList(), productId);
        }

        // 准备所有需要提取特征的商品ID，包括当前商品
        Set<String> featureIds = new LinkedHashSet<>();
        featureIds.add(productId);
        candidateProducts.stream()
                .map(Product::getId)
                .filter(Objects::nonNull)
                .forEach(featureIds::add);

        if (featureIds.isEmpty()) {
            log.warn("No candidate feature ids collected, productId={}, using basic ranking fallback", productId);
            return buildSimilarProductsResponse(resolvedLimit, candidateProducts, productId);
        }

        // 查询所有候选商品的特征数据
        List<ProductFeatureDto> featureDtos = recommendMapper.getProductFeaturesByIds(new ArrayList<>(featureIds));

        // 没有特征，直接退化为候选的顺序
        if (featureDtos == null || featureDtos.isEmpty()) {
            log.warn("没有找到特征数据，商品id={}，退化到基本排名", productId);
            return buildSimilarProductsResponse(resolvedLimit, candidateProducts, productId);
        }

        // 转化为算法用的Feature对象
        List<ProductFeature> productFeatures = featureDtos.stream()
                .map(this::convertToProductFeature)
                .filter(Objects::nonNull)
                .collect(Collectors.toCollection(ArrayList::new));

        if (productFeatures.size() <= 1) {
            log.warn("特征数据不足，无法运行推荐算法，商品id={}，特征数量={}", productId, productFeatures.size());
            return buildSimilarProductsResponse(resolvedLimit, candidateProducts, productId);
        }

        // like类型做为偏好标签
        List<String> preferenceTags = (current.getType() != null && !current.getType().isBlank())
                ? Collections.singletonList(current.getType())
                : null;

        // 用推荐算法排序
        RecommendationResult recommendationResult = ProductsRecommendAlgorithm.recommend(
                productFeatures,
                preferenceTags
        );

        // 通过推荐结果转为最终返回数据
        List<ProductResponse> recommendedResponses = new ArrayList<>();
        Set<String> recommendedIds = new LinkedHashSet<>();
        for (ScoredProduct scoredProduct : recommendationResult.getProducts()) {
            if (recommendedResponses.size() >= resolvedLimit) {
                break;
            }
            ProductFeature feature = scoredProduct.getFeature();
            if (feature == null || feature.getProductId() == null || feature.getProductId().equals(productId)) {
                continue;
            }
            Product candidate = candidateMap.get(feature.getProductId());
            if (candidate == null) {
                continue;
            }
            if (recommendedIds.add(feature.getProductId())) {
                recommendedResponses.add(toProductResponse(candidate));
            }
        }

        // 推荐数量不够时用候选补齐
        if (recommendedResponses.size() < resolvedLimit) {
            for (Product candidate : candidateProducts) {
                if (candidate == null || candidate.getId() == null || candidate.getId().equals(productId)) {
                    continue;
                }
                if (recommendedIds.add(candidate.getId())) {
                    recommendedResponses.add(toProductResponse(candidate));
                }
                if (recommendedResponses.size() >= resolvedLimit) {
                    break;
                }
            }
        }

        // 构建最终响应
        SimilarProductsResponse response = new SimilarProductsResponse();
        response.setSimilarProducts(recommendedResponses);

        log.info("相似商品获取完成，商品id={}，请求数量={}，实际数量={}，候选商品数量={}，特征数量={}",
                productId, resolvedLimit, response.getSimilarProducts().size(), candidateProducts.size(), productFeatures.size());
        return response;
    }
 
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ProductStandardizeResponse standardizeProduct(String productId) {
        // 参数校验：商品ID不能为空
        if (productId == null) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "商品ID不能为空");
        }

        // 查询当前商品信息
        Product current = productsMapper.selectById(productId);
        if (current == null) {
            throw new BusinessException(ResultCode.PRODUCT_NOT_FOUND);
        }

        // 准备更新对象
        Product toUpdate = new Product();
        toUpdate.setId(current.getId());

        // 记录更新的字段
        List<String> updatedFields = new ArrayList<>();
        // TODO: 利用具体算法完成商品数据标准化
        
        // 标准化商品名称：去除多余空格，首字母大写
        String standardizedName = standardizeName(current.getProductName());
        if (standardizedName != null && !Objects.equals(standardizedName, current.getProductName())) {
            toUpdate.setProductName(standardizedName);
            updatedFields.add("nameFormat");
        }

        // 标准化价格：转为正数
        BigDecimal standardizedPrice = standardizePrice(current.getPrice());
        if (standardizedPrice != null && standardizedPrice.compareTo(current.getPrice()) != 0) {
            toUpdate.setPrice(standardizedPrice);
            updatedFields.add("price");
        }

        // 标准化图片URL：去除首尾空格
        String standardizedPictureUrl = trimToNullIfUnchanged(current.getPictureUrl());
        if (standardizedPictureUrl != null && !Objects.equals(standardizedPictureUrl, current.getPictureUrl())) {
            toUpdate.setPictureUrl(standardizedPictureUrl);
            updatedFields.add("pictureUrl");
        }

        // 标准化商品链接：去除首尾空格
        String standardizedLink = trimToNullIfUnchanged(current.getLink());
        if (standardizedLink != null && !Objects.equals(standardizedLink, current.getLink())) {
            toUpdate.setLink(standardizedLink);
            updatedFields.add("link");
        }

        // 标准化销量：转为非负数
        Integer standardizedSalesQuantity = standardizeSales(current.getSalesQuantity());
        if (standardizedSalesQuantity != null && !Objects.equals(standardizedSalesQuantity, current.getSalesQuantity())) {
            toUpdate.setSalesQuantity(standardizedSalesQuantity);
            updatedFields.add("salesQuantity");
        }

        // 如果有字段需要更新，则执行更新操作
        if (!updatedFields.isEmpty()) {
            int affected = productsMapper.updateProduct(toUpdate);
            if (affected <= 0) {
                throw new BusinessException(ResultCode.DATABASE_ERROR, "商品数据标准化失败");
            }
            log.info("Product {} standardized, updatedFields={}", productId, updatedFields);
        } else {
            log.info("Product {} already standardized, no fields updated", productId);
        }

        // 构建响应对象
        ProductStandardizeResponse response = new ProductStandardizeResponse();
        response.setProductId(productId);
        response.setStandardized(!updatedFields.isEmpty());
        response.setUpdatedFields(updatedFields);
        return response;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public com.jingxuan.dto.response.ProductResponse addProduct(com.jingxuan.dto.request.ProductSaveRequest request) {
        Product product = new Product();
        // 使用UUID作为ID
        String newId = java.util.UUID.randomUUID().toString().replace("-", "").substring(0, 9);
        // 尝试解析为数字以便保持格式一致性，如果不是必须的也可以直接用UUID
        // 这里为了兼容之前的数字ID风格，尝试生成9位数字字符串
        // 但为了保证唯一性，混合时间戳
        newId = String.valueOf(System.currentTimeMillis()).substring(4); 
        
        product.setId(newId);
        product.setProductName(request.getProductName());
        product.setPictureUrl(request.getPictureUrl());
        product.setPrice(request.getPrice());
        product.setApplauseRate(request.getApplauseRate() != null ? request.getApplauseRate() : 0f);
        product.setDescribe(request.getDescribe());
        product.setLink(request.getLink());
        product.setType(request.getType());
        product.setSalesQuantity(request.getSalesQuantity() != null ? request.getSalesQuantity() : 0);
        product.setPlatformId(request.getPlatformId());
        
        productsMapper.insert(product);
        return toProductResponse(product);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public com.jingxuan.dto.response.ProductResponse updateProduct(String productId, com.jingxuan.dto.request.ProductSaveRequest request) {
        Product product = productsMapper.selectById(productId);
        if (product == null) {
            throw new BusinessException(ResultCode.PRODUCT_NOT_FOUND);
        }
        if (request.getProductName() != null) product.setProductName(request.getProductName());
        if (request.getPrice() != null) product.setPrice(request.getPrice());
        if (request.getPictureUrl() != null) product.setPictureUrl(request.getPictureUrl());
        if (request.getApplauseRate() != null) product.setApplauseRate(request.getApplauseRate());
        if (request.getDescribe() != null) product.setDescribe(request.getDescribe());
        if (request.getLink() != null) product.setLink(request.getLink());
        if (request.getType() != null) product.setType(request.getType());
        if (request.getSalesQuantity() != null) product.setSalesQuantity(request.getSalesQuantity());
        if (request.getPlatformId() != null) product.setPlatformId(request.getPlatformId());

        productsMapper.updateProduct(product);
        return toProductResponse(product);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteProduct(String productId) {
        productsMapper.deleteById(productId);
    }

    @Override
    public ProductsResponse listProducts(ProductListRequest request) {
        int page = resolvePositiveNumber(request == null ? null : request.getPage(), DEFAULT_PAGE);
        int pageSize = Math.min(resolvePositiveNumber(request == null ? null : request.getPageSize(), DEFAULT_PAGE_SIZE), MAX_PAGE_SIZE);
        int offset = Math.max(0, (page - 1) * pageSize);
        String keyword = request != null && request.getKeyword() != null ? request.getKeyword().trim() : null;
        if (keyword != null && keyword.isEmpty()) {
            keyword = null;
        }

        List<Product> products = productsMapper.selectProductList(keyword, offset, pageSize);
        int total = productsMapper.countProductList(keyword);

        ProductsResponse response = new ProductsResponse();
        response.setProducts(products.stream().map(this::toProductResponse).collect(Collectors.toList()));
        response.setTotalCount(total);
        response.setPage(page);
        response.setPageSize(pageSize);
        return response;
    }

    private void addCandidates(Map<String, Product> accumulator, List<Product> candidates) {
        if (candidates == null || candidates.isEmpty()) {
            return;
        }
        for (Product candidate : candidates) {
            if (candidate == null || candidate.getId() == null) {
                continue;
            }
            accumulator.putIfAbsent(candidate.getId(), candidate);
        }
    }

    /**
     * 构建相似商品响应
     */
    private SimilarProductsResponse buildSimilarProductsResponse(int limit, List<Product> candidates, String excludeProductId) {
        SimilarProductsResponse response = new SimilarProductsResponse();
        if (candidates == null || candidates.isEmpty()) {
            response.setSimilarProducts(Collections.emptyList());
            return response;
        }
        // 构建相似商品列表
        List<ProductResponse> items = new ArrayList<>();
        for (Product candidate : candidates) {
            if (candidate == null || candidate.getId() == null || candidate.getId().equals(excludeProductId)) {
                continue;
            }
            items.add(toProductResponse(candidate));
            if (items.size() >= limit) {
                break;
            }
        }
        response.setSimilarProducts(items);
        return response;
    }

    /**
     * 转换为算法用的Feature对象
     */
    private ProductFeature convertToProductFeature(ProductFeatureDto dto) {
        if (dto == null || dto.getProductId() == null || dto.getPrice() == null) {
            return null;
        }
        return ProductFeature.builder()
                .productId(dto.getProductId())
                .price(dto.getPrice())
                .goodRate(normalizePositiveRate(dto.getPositiveRate()))
                .commentCount(dto.getCommentCount() == null ? 0 : dto.getCommentCount())
                .lastCommentTime(dto.getLastCommentTime())
                .productType(dto.getProductType())
                .build();
    }

    /**
     * 归一化好评率
     */
    private double normalizePositiveRate(Double positiveRate) {
        if (positiveRate == null) {
            return 0.5;
        }
        double value = positiveRate;
        if (value > 1.0) {
            value = value / 100.0;
        }
        if (value < 0.0) {
            return 0.0;
        }
        if (value > 1.0) {
            return 1.0;
        }
        return value;
    }

    /**
     * 转换为商品响应对象
     */
    private ProductResponse toProductResponse(Product product) {
        ProductResponse response = new ProductResponse();
        response.setProductId(product.getId());
        response.setProductName(product.getProductName());
        response.setPrice(product.getPrice());
        response.setPlatformName(resolvePlatformName(product.getPlatformId()));
        response.setImageUrl(product.getPictureUrl());
        response.setProductUrl(product.getLink());
        response.setSalesQuantity(product.getSalesQuantity());
        response.setApplauseRate(product.getApplauseRate());
        response.setDescription(product.getDescribe());
        
        // 设置相关性得分（如果有）
        response.setRelevanceScore(product.getRelevanceScore());
        
        // 从数据库获取评价数据
        try {
            response.setReviews(getProductReviewsFromDatabase(product.getId()));
        } catch (Exception e) {
            log.warn("获取商品评价失败，商品ID: {}", product.getId(), e);
            response.setReviews(java.util.Collections.singletonList("暂无评价"));
        }
        
        return response;
    }
    
    /**
     * 从数据库获取商品评价
     */
    private java.util.List<String> getProductReviewsFromDatabase(String productId) {
        try {
            // 通过CommentsMapper查询数据库获取评价
            // 使用selectCommentsByProductId方法，设置合理的分页参数（获取前10条）
            List<Comment> comments = commentsMapper.selectCommentsByProductId(productId, 0, 10);
            
            if (comments == null || comments.isEmpty()) {
                return java.util.Collections.emptyList();
            }
            
            // 将评价转换为字符串格式
            return comments.stream()
                    .map(comment -> comment.getUserName() + ": " + comment.getContent())
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("查询商品评价失败，商品ID: {}", productId, e);
            return java.util.Collections.emptyList();
        }
    }

    /**
     * 根据平台ID解析平台名称
     */
    private String resolvePlatformName(Integer platformId) {
        if (platformId == null) {
            return "未知平台";
        }
        return switch (platformId) {
            case 1 -> "淘宝";
            case 2 -> "京东";
            default -> "未知平台";
        };
    }

    /**
     * 解析正整数，若为空或小于等于0则返回默认值
     */
    private int resolvePositiveNumber(Integer value, int defaultValue) {
        return (value == null || value <= 0) ? defaultValue : value;
    }

    /**
     * 标准化商品名称
     */
    private String standardizeName(String name) {
        if (name == null) {
            return null;
        }
        // 去除首尾空格，将连续多个空格替换为单个空格
        String normalized = name.trim().replaceAll("\\s{2,}", " ");
        if (!normalized.isEmpty()) {
            // 首字母大写
            char first = normalized.charAt(0);
            normalized = Character.toUpperCase(first) + normalized.substring(1);
        }
        return normalized;
    }

    /**
     * 标准化价格
     */
    private BigDecimal standardizePrice(BigDecimal price) {
        if (price == null) {
            return null;
        }
        return price.compareTo(BigDecimal.ZERO) < 0 ? price.abs() : price;
    }

    /**
     * 去除字符串首尾空格
     */
    private String trimToNullIfUnchanged(String value) {
        if (value == null) {
            return null;
        }
        String trimmed = value.trim();
        return trimmed;
    }

    /**
     * 标准化销量
     */
    private Integer standardizeSales(Integer salesQuantity) {
        if (salesQuantity == null) {
            return null;
        }
        return Math.max(0, salesQuantity);
    }
}
